//TODO 静态反射
// 1 首先定义一个生成类的宏
// 2 其次定义一个函数完成如下功能：
// 2.1 生成一个.cpp文件
// 2.2 解析json文件，依据json通过类宏在创建的.cpp文件中递归生成类
// 2.2 在.cpp文件的末尾创建一个static的类成员变量。

#include "json.h"
#include "AbstractFactory.h"
#include "UIBase.h"

#include <iostream>
#include <fstream>
#include <string>

void GenerateClass(const Json::Value& cfg, std::ofstream& ofs, std::string layer = "Main") {
    //2. 解析json对象: 1. 依据json生成对象，2.将生成的对象insert到对象池中
    //进到这个函数里面就要首先生成有个Page

    ofs << std::string("CLASSHEAD(") + layer + std::string(")\n");
    Json::Value::Members mem = cfg.getMemberNames();
    std::string buffer;
    for(auto iter = mem.begin(); iter != mem.end(); ++iter) {
        if(!cfg[*iter].isObject()) {
            continue ;
        }
        if(!cfg[*iter].isMember("property")) {
            continue ;
        }
        std::string tmplayer = layer + "_" + *iter;
        if("Page" == cfg[*iter]["property"].asString()) {
            GenerateClass(cfg[*iter], ofs, tmplayer);
            buffer += "static Page" + tmplayer + " " + tmplayer + "(" + ");\n";
        } else {
            //NOTE 非Page属性的生成字符串
            //需要修改接口类UIBase,新增buidObject接口，用于返回创建这个类对象的代码字符串
            //所以在调用buildObejct之前就要调用InitGUI，即需要引入libgui.a库
            std::shared_ptr<UIBase> ptr = AbstractFactory::getObject<UIBase>(cfg[*iter]["property"].asString());
            buffer += ptr->buidObject(cfg[*iter]);
            buffer += "\n";
        }

    }
    ofs << std::string("CLASSBODY(") + layer + std::string(")\n");
    ofs << buffer;
    ofs << "\n\n";
    ofs << std::string("CLASSTAIL");
    //NOTE 全部创建完成之后则需要创建该类的对象，然后Insert到对象池中
}

int main() {
    //1. 读取配置文件转为json对象
    Json::Value GlobalCustomeCfg = Json::nullValue;
    std::ifstream ifs;
    ifs.open("./PageJsonFile.json", std::ios::in);
    if(!ifs.is_open()) {
        return -1;
    }
    std::string content;
    while(!ifs.eof()) {
        std::string str;
        ifs >> str;
        content += str;
    }
    ifs.close();
    Json::Reader jsonReader;
    jsonReader.parse(content, GlobalCustomeCfg);
    //TODO 这里创建一个.cpp文件，然后通过GenerateClass将json的其他内容都写到一个buffer里面，
    //然后再将buffer写到创建的.cpp文件里面
    std::ofstream ofs("GeneratorPage.cpp", std::ios::out);
    //1. 包含头文件
    ofs <<  "#include \"json.h\"\n#include \"AbstractFactory.h\"\n#include \"ClassObjectPool.h\"\n#include \"UIBase.h\"\n\n\n";
    //2. 定义宏
    ofs << "#define CLASSHEAD(CLASSNAME) \\\nclass Page##CLASSNAME: public PageBase {\\\npublic:\\\nvoid MsgProc() {\\\nClassObjectPool obj;\\\nstd::shared_ptr<PageUsr> msgProcCls = obj.Get<PageUsr>(GetPageName());\\\nmsgProcCls->MsgProc();\\\n}\\\nvoid UpData() {\\\nClassObjectPool obj;\\\nstd::shared_ptr<PageUsr> msgProcCls = obj.Get<PageUsr>(GetPageName());\\\nmsgProcCls->UpData();    \\\n}\\\n\n\n#define CLASSBODY(CLASSNAME) \\\nPage##CLASSNAME(const int x, const int y, const int width, const int height)\\\n:PageBase()\\\n{\\\n\n\n#define CLASSTAIL\\\nMessageBus bus;\\\nbus.Attach([this]() {\\\nMsgProc();\\\n}, \"GUI\");\\\n\\nbus.Attach([this]() {\\\nUpData();\\\n}, \"STATUS\");}\\\n";

    //2. extern
    ofs << "\nextern \"C\" void InitGUI();\n\n\n";
    GenerateClass(GlobalCustomeCfg, ofs);
    ofs.close();
    return 0;
}